﻿  ﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Configuration;
using EFCachingProvider.Caching;
using EFCachingProvider;
using EFProviderWrapperToolkit;
using System.Data.EntityClient;
  ﻿using TSharp.Core.Util;

namespace TSharp.Core.Repository
{
    public class CachedContextConnectionFactory : System.Data.Entity.Infrastructure.IDbConnectionFactory
    {
        private static System.Data.Entity.Infrastructure.SqlConnectionFactory sqlfactory =
            new System.Data.Entity.Infrastructure.SqlConnectionFactory();
        private static Func<string, DbConnection> factory;
        static CachedContextConnectionFactory()
        {
            var tracing = "EFTracing:Enable".GetAppSetting(k => k.ToBoolean(true));
            var caching = "EFCaching:Enable".GetAppSetting(k => k.ToBoolean(true));
            if (tracing && caching)
            {
                factory = nameOrConnectionString => CreateEntityConnectionWithWrappers(nameOrConnectionString, "EFTracingProvider", "EFCachingProvider");
            }
            else if (tracing)
            {
                factory = nameOrConnectionString => CreateEntityConnectionWithWrappers(nameOrConnectionString, "EFTracingProvider");
            }
            else if (caching)
            {
                factory =
                    nameOrConnectionString =>
                    CreateEntityConnectionWithWrappers(nameOrConnectionString, "EFCachingProvider");
            }
            else
            {
                factory =
                    nameOrConnectionString => CreateEntityConnectionWithWrappers(nameOrConnectionString);
            }
        }
        public CachedContextConnectionFactory()
        {

        }
        public DbConnection CreateConnection(string nameOrConnectionString)
        {
            return factory(nameOrConnectionString);
        }

        /// <summary>
        /// Creates the entity connection with wrappers.
        /// </summary>
        /// <param name="entityConnectionString">The original entity connection string. This may also be a single word, e.g., "MyEntities", in which case it is translated into "name=MyEntities" and looked up in the application configuration.</param>
        /// <param name="wrapperProviders">List for wrapper providers.</param>
        /// <returns>EntityConnection object which is based on a chain of providers.</returns>
        public static DbConnection CreateEntityConnectionWithWrappers(string entityConnectionString, params string[] wrapperProviders)
        {
            // If there is only a single word in the connection string, treat it as the value for Name.
            if (!entityConnectionString.Contains('='))
                entityConnectionString = "name=" + entityConnectionString;
            DbConnection storeConnection;
            if (entityConnectionString.Contains("name"))
            {
                var ecsb = new EntityConnectionStringBuilder(entityConnectionString);
                // if connection string is name=EntryName, look up entry in the config file and parse it
                if (!String.IsNullOrEmpty(ecsb.Name))
                {
                    var connStr = ConfigurationManager.ConnectionStrings[ecsb.Name];
                    if (connStr == null)
                    {
                        throw new ArgumentException("Specified named connection string '" + ecsb.Name +
                                                    "' was not found in the configuration file.");
                    }
                    ecsb.ProviderConnectionString = connStr.ConnectionString;
                    ecsb.Provider = connStr.ProviderName;
                }
                storeConnection = DbProviderFactories.GetFactory(ecsb.Provider).CreateConnection();
                storeConnection.ConnectionString = ecsb.ProviderConnectionString;
            }
            else
            {
                storeConnection = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateConnection();
                storeConnection.ConnectionString = entityConnectionString;
            }




            var newEntityConnection = DbConnectionWrapper.WrapConnection(storeConnection, wrapperProviders);
            return newEntityConnection;
        }
    }
}